package post

import (
	"context"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/service/backend/common/errorx"
	"mall/service/backend/common/i18n"
	"mall/service/forum/model"
	"mall/service/forum/rpc/internal/svc"
	"mall/service/forum/rpc/internal/utils"
	"mall/service/forum/rpc/internal/utils/errorhandler"
	"mall/service/forum/rpc/types/forum"

	"github.com/volatiletech/null/v8"
	"github.com/zeromicro/go-zero/core/logx"
)

type BackendCreatePostLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBackendCreatePostLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackendCreatePostLogic {
	return &BackendCreatePostLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// ##24.10.22##  后台发布香评
func (l *BackendCreatePostLogic) BackendCreatePost(in *forum.ForumPostInfo) (*forum.BaseIDResp, error) {
	// logx.Infof("BackendCreatePost : %+v ", in)

	if in.PostTitle == nil || len(strings.TrimSpace(*in.PostTitle)) == 0 {
		return nil, errorx.NewInvalidArgumentError("forum.postTitleRequired")
	}

	if in.AuthorId == nil || *in.AuthorId == 0 {
		return nil, errorx.NewInvalidArgumentError("forum.postAuthorRequired")
	}

	if in.PostContent == nil {
		return nil, errorx.NewInvalidArgumentError("forum.postContentRequired")
	}

	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	now := time.Now()
	post := &model.ForumPost{
		ForumID:          uint64(l.svcCtx.Config.Query.ColumnForumId),
		PostTitle:        strings.TrimSpace(*in.PostTitle),
		PostContent:      *in.PostContent,
		PostAuthorID:     *in.AuthorId,
		PublicDate:       now,
		PostDate:         now,
		PostModifiedDate: now,
	}

	author, err := l.svcCtx.User.FindOne(l.ctx, *in.AuthorId)
	if err != nil {
		logx.Errorw("BackendCreatePost User FindOne err", logx.Field("detail", err.Error()))
	} else {
		post.PostAuthorNickname = author.UserNickname
		post.PostAuthorEmail = author.UserEmail
		post.PostAuthorAvatar = author.UserAvatar
	}

	if in.PostContentFiltered != nil {
		post.PostContentFiltered = *in.PostContentFiltered
	}
	if in.PostExcerpt != nil && len(strings.TrimSpace(*in.PostExcerpt)) > 0 {
		post.PostExcerpt = strings.TrimSpace(*in.PostExcerpt)
	}

	if in.Status != nil {
		post.PostStatus = uint8(*in.Status)
	} else {
		post.PostStatus = uint8(globalkey.StatusPending)
	}
	if post.PostStatus != uint8(globalkey.StatusApproved) { // 待发布，故意设置一个无效时间，以便后续判断
		post.PublicDate = now.Add(time.Minute * -1)
	}
	if in.CommentStatus != nil && *in.CommentStatus > 0 {
		post.CommentStatus = 1
	}
	if in.Sort != nil {
		post.Sort = uint16(*in.Sort)
	} else {
		post.Sort = uint16(9999)
	}

	rel := &model.ForumPostRel{
		TagIds: in.TagIds,
	}
	if len(in.Meta) > 0 {
		for _, v := range in.Meta {
			if v.Key == nil || len(strings.TrimSpace(*v.Key)) == 0 {
				continue
			}

			if v.Value == nil || len(strings.TrimSpace(*v.Value)) == 0 {
				continue
			}

			rel.Meta = append(rel.Meta, &model.ForumPostMetum{
				MetaKey:   strings.TrimSpace(*v.Key),
				MetaValue: null.StringFrom(strings.TrimSpace(*v.Value)),
			})
		}
	}

	allCardMap := make(map[string]bool)
	if len(in.AllCard) > 0 {
		for _, v := range in.AllCard {
			if v.LinkUrl != nil && len(strings.TrimSpace(*v.LinkUrl)) > 0 {
				allCardMap[strings.TrimSpace(*v.LinkUrl)] = true
			}
		}
	}

	if len(in.NewCard) > 0 {
		for _, v := range in.NewCard {
			if v.LinkUrl == nil || len(strings.TrimSpace(*v.LinkUrl)) == 0 {
				continue
			}

			linkUrl := strings.TrimSpace(*v.LinkUrl)
			if _, ok := allCardMap[linkUrl]; !ok {
				continue
			}

			delete(allCardMap, linkUrl)

			if v.Type == nil || len(strings.TrimSpace(*v.Type)) == 0 {
				continue
			}

			if v.Title == nil || len(strings.TrimSpace(*v.Title)) == 0 {
				continue
			}

			var objectType int32 = utils.ParseCardType(strings.TrimSpace(*v.Type))
			card := &model.ForumPostCard{
				ObjectType: uint16(objectType),
				LinkURL:    linkUrl,
				Title:      strings.TrimSpace(*v.Title),
			}

			if v.Id != nil && *v.Id > 0 {
				card.ObjectID = *v.Id
			}
			if v.PicUrl != nil && len(strings.TrimSpace(*v.PicUrl)) > 0 {
				card.PicURL = strings.TrimSpace(*v.PicUrl)
			}
			if v.Subtitle != nil && len(strings.TrimSpace(*v.Subtitle)) > 0 {
				card.Subtitle = strings.TrimSpace(*v.Subtitle)
			}
			if v.Label != nil && len(strings.TrimSpace(*v.Label)) > 0 {
				card.Label = strings.TrimSpace(*v.Label)
			}
			if v.Price != nil && len(strings.TrimSpace(*v.Price)) > 0 {
				card.Price = strings.TrimSpace(*v.Price)
			}

			rel.Card = append(rel.Card, card)
		}
	}

	allMediaMap := make(map[string]string)
	if len(in.AllMedia) > 0 {
		for _, v := range in.AllMedia {
			if v.Id != nil && v.Url != nil && len(*v.Id) > 0 && len(*v.Url) > 0 {
				allMediaMap[*v.Id] = *v.Url
			}
		}
	}

	if len(in.NewMedia) > 0 {
		var thumbnailOrder uint
		var thumbnailId uint64
		var thumbnailUrl string
		for idx, v := range in.NewMedia {
			var url string
			if v.Url != nil && len(*v.Url) > 0 { // v.Uri  content版本（包含?id）  v.Url  url当前版本 | attachment当前版本
				url = *v.Url
			}
			var uri string
			if v.Uri != nil && len(*v.Uri) > 0 {
				uri = *v.Uri
				if len(url) == 0 {
					url = uri
				}
			}
			if len(url) == 0 {
				continue
			}

			var thumbnail uint8
			if v.Thumbnail != nil && *v.Thumbnail > 0 {
				thumbnail = uint8(*v.Thumbnail)
			}
			var order uint
			if v.Order != nil {
				order = uint(*v.Order)
			} else {
				order = uint(idx) + globalkey.AttachmentOrderOffset
			}
			var altText string
			if v.AltText != nil && len(*v.AltText) > 0 {
				altText = *v.AltText
			}

			var meta []string
			if v.Name != nil && len(*v.Name) > 0 {
				meta = append(meta, "filename:"+*v.Name)
				if len(altText) == 0 {
					altText = *v.Name
				}
			}
			if v.MetaData != nil && len(*v.MetaData) > 0 {
				meta = append(meta, *v.MetaData)
			}
			if v.MimeType != nil && len(*v.MimeType) > 0 {
				meta = append(meta, "mimeType:"+*v.MimeType)
			}
			metaData := strings.Join(meta, ";")

			var mediaId uint64
			if v.Id != nil && len(*v.Id) > 0 {
				if i, err := strconv.ParseInt(*v.Id, 10, 64); err == nil {
					mediaId = uint64(i)
				}
			}

			media := &model.ForumAttachmentRelationship{
				AttachmentID:        mediaId,
				AttachmentThumbnail: thumbnail,
				AttachmentOrder:     order,
				AttachmentImageURL:  url,
				AttachmentImageAlt:  altText,
				AttachmentImageMeta: metaData,
			}

			if thumbnail == 0 && mediaId > 0 { // thumbnail == 0 不是缩略图， mediaId > 0 不是外链，获取图文uri
				if uri, ok := allMediaMap[*v.Id]; ok {
					media.AttachmentSource = uri
				}
			}

			rel.Media = append(rel.Media, media)

			if thumbnail > 0 && (len(thumbnailUrl) == 0 || thumbnailOrder > order) {
				thumbnailOrder = order
				thumbnailId = mediaId
				thumbnailUrl = url
			}
		}

		if len(thumbnailUrl) > 0 {
			rel.Meta = append(rel.Meta, &model.ForumPostMetum{
				MetaKey:   "_thumbnail_id",
				MetaValue: null.StringFrom(strconv.FormatInt(int64(thumbnailId), 10)),
			})
			rel.Meta = append(rel.Meta, &model.ForumPostMetum{
				MetaKey:   "_thumbnail_url",
				MetaValue: null.StringFrom(thumbnailUrl),
			})

			rel.Feed = &model.ForumFeed{
				ForumID:        post.ForumID,
				AuthorID:       post.PostAuthorID,
				AuthorNickname: post.PostAuthorNickname,
				AuthorAvatar:   post.PostAuthorAvatar,
				Excerpt:        post.PostExcerpt,
				ThumbnailID:    thumbnailId,
				ThumbnailURL:   thumbnailUrl,
				Status:         uint8(globalkey.StatusPending),
			}
			if post.PostStatus == uint8(globalkey.StatusApproved) {
				rel.Feed.Status = uint8(globalkey.StatusApproved)
			}
		}
		rel.Meta = append(rel.Meta, &model.ForumPostMetum{
			MetaKey:   "_photo_count",
			MetaValue: null.StringFrom(strconv.FormatInt(int64(len(rel.Media)), 10)),
		})
	}

	err = l.svcCtx.Post.Insert(l.ctx, tx, post, rel)
	if err != nil {
		tx.Rollback()
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	tx.Commit()

	return &forum.BaseIDResp{
		Id:  post.PostID,
		Msg: i18n.CreateSuccess,
	}, nil
}
